using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;

namespace ZeroSum.App.Extensions;

/// <summary>
///     Http 拓展类
/// </summary>
public static class HttpContextExtensions
{
    /// <summary>
    ///     获取 Action 特性
    /// </summary>
    /// <typeparam name="TAttribute"></typeparam>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public static TAttribute? GetMetadata<TAttribute>(this HttpContext httpContext)
        where TAttribute : class
    {
        return httpContext.GetEndpoint()?.Metadata?.GetMetadata<TAttribute>();
    }

    /// <summary>
    ///     获取 控制器/Action 描述器
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public static ControllerActionDescriptor? GetControllerActionDescriptor(this HttpContext httpContext)
    {
        return httpContext.GetEndpoint()?.Metadata?.FirstOrDefault(u => u is ControllerActionDescriptor) as
            ControllerActionDescriptor;
    }

    /// <summary>
    ///     设置规范化文档自动登录
    /// </summary>
    /// <param name="httpContext"></param>
    /// <param name="accessToken"></param>
    public static void SigninToSwagger(this HttpContext httpContext, string? accessToken)
    {
        // 设置 Swagger 刷新自动授权
        httpContext.Response.Headers["access-token"] = accessToken;
    }

    /// <summary>
    ///     设置规范化文档退出登录
    /// </summary>
    /// <param name="httpContext"></param>
    public static void SignoutToSwagger(this HttpContext httpContext)
    {
        httpContext.Response.Headers["access-token"] = "invalid_token";
    }

    /// <summary>
    ///     获取本机 IPv4地址
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public static string? GetLocalIpAddressToIPv4(this HttpContext context)
    {
        return context.Connection.LocalIpAddress?.MapToIPv4()?.ToString();
    }

    /// <summary>
    ///     获取本机 IPv6地址
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public static string? GetLocalIpAddressToIPv6(this HttpContext context)
    {
        return context.Connection.LocalIpAddress?.MapToIPv6()?.ToString();
    }

    /// <summary>
    ///     获取远程 IPv4地址
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public static string? GetRemoteIpAddressToIPv4(this HttpContext context)
    {
        return context.Connection.RemoteIpAddress?.MapToIPv4()?.ToString();
    }

    /// <summary>
    ///     获取远程 IPv6地址
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public static string? GetRemoteIpAddressToIPv6(this HttpContext context)
    {
        return context.Connection.RemoteIpAddress?.MapToIPv6()?.ToString();
    }

    /// <summary>
    ///     获取完整请求地址
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    public static string GetRequestUrlAddress(this HttpRequest request)
    {
        return new StringBuilder()
            .Append(request.Scheme)
            .Append("://")
            .Append(request.Host)
            .Append(request.PathBase)
            .Append(request.Path)
            .Append(request.QueryString)
            .ToString();
    }

    /// <summary>
    ///     获取来源地址
    /// </summary>
    /// <param name="request"></param>
    /// <param name="refererHeaderKey"></param>
    /// <returns></returns>
    public static string GetRefererUrlAddress(this HttpRequest request, string refererHeaderKey = "Referer")
    {
        return request.Headers[refererHeaderKey].ToString();
    }

    /// <summary>
    ///     确定指定的 HTTP 请求是否为 AJAX 请求。
    /// </summary>
    /// <returns>
    ///     如果指定的 HTTP 请求是 AJAX 请求，则为 true；否则为 false。
    /// </returns>
    /// <param name="request">HTTP 请求。</param>
    /// <exception cref="T:System.ArgumentNullException"><paramref name="request" /> 参数为 null（在 Visual Basic 中为 Nothing）。</exception>
    public static bool IsAjaxRequest(this HttpRequest request)
    {
        return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal)
               || string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
    }

    /// <summary>
    ///     确定指定的 HTTP 请求的 ContextType 是否为 Json 方式
    /// </summary>
    public static bool IsJsonContextType(this HttpRequest request)
    {
        var flag = request.Headers?["Content-Type"].ToString()
                       .IndexOf("application/json", StringComparison.OrdinalIgnoreCase) > -1
                   || request.Headers?["Content-Type"].ToString()
                       .IndexOf("text/json", StringComparison.OrdinalIgnoreCase) > -1;
        if (flag) return true;
        flag = request.Headers?["Accept"].ToString().IndexOf("application/json", StringComparison.OrdinalIgnoreCase) >
               -1
               || request.Headers?["Accept"].ToString().IndexOf("text/json", StringComparison.OrdinalIgnoreCase) > -1;
        return flag;
    }

    /// <summary>
    ///     获取<see cref="HttpRequest" />的请求数据
    /// </summary>
    /// <param name="request">请求信息</param>
    /// <param name="key">要获取数据的键名</param>
    /// <returns></returns>
    public static string? Params(this HttpRequest request, string key)
    {
        if (request.Query.ContainsKey(key)) return request.Query[key];
        if (request.HasFormContentType) return request.Form[key];
        return null;
    }

    /// <summary>
    ///     获取客户端IP地址
    /// </summary>
    public static string? GetClientIp(this HttpContext context)
    {
        var ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
        if (string.IsNullOrEmpty(ip)) ip = context.Connection.RemoteIpAddress?.ToString();

        return ip;
    }
}